package com.ideaaedi.component.decompile.fernflower;

import com.ideaaedi.component.decompile.Decompiler;
import org.jboss.windup.decompiler.fernflower.FernflowerDecompiler;
import org.jetbrains.java.decompiler.main.Fernflower;
import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger;
import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;

import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;


/**
 * fernflower反编译器
 *
 * @author JustryDeng
 * @since 2021/9/29 15:33:14
 */
public class FfDecompiler extends FernflowerDecompiler implements Decompiler {
    
    @Override
    public LinkedHashMap<String, String> decompile(Collection<byte[]> classByteCollection, String methodName) {
        // options
        Map<String, Object> options = new HashMap<>(IFernflowerPreferences.DEFAULTS);
        // 反编译泛型
        options.put(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1");
        
        // IBytecodeProvider
        Map<String, byte[]> classProvider = new HashMap<>(8);
        String visualPathname;
        for (byte[] classBytes : classByteCollection) {
            visualPathname = MemoryBytecodeProvider.SPECIAL_KEY_PREFIX + UUID.randomUUID().toString().replace("-", "") + ".class";
            classProvider.put(visualPathname, classBytes);
        }
        IBytecodeProvider bytecodeProvider = new MemoryBytecodeProvider(options, classProvider);
        
        // IResultSaver
        MemoryResultSaver memoryResultSaver = new MemoryResultSaver();
        
        // 反编译引擎
        Fernflower fernflower = new Fernflower(bytecodeProvider, memoryResultSaver, options, new PrintStreamLogger(System.out));
        // 添加反编译文件
        for (String pathname : classProvider.keySet()) {
            fernflower.getStructContext().addSpace(new File(pathname), true);
        }
        // 执行反编译
        fernflower.decompileContext();
        return memoryResultSaver.getResult();
    }
}
